#!/bin/bash
# * =====================================================
# * Copyright © hk. 2022-2025. All rights reserved.
# * File name  : net-nfs.sh
# * Author     : 苏木
# * Date       : 2025-10-24
# * Version    : 
# * Description: 
# * ======================================================
##

# 脚本和工程路径
# ========================================================
SCRIPT_NAME=${0#*/}
SCRIPT_CURRENT_PATH=${0%/*}
SCRIPT_ABSOLUTE_PATH=`cd $(dirname ${0}); pwd`
PROJECT_ROOT=${SCRIPT_ABSOLUTE_PATH}/.. # 工程的源码目录，一定要和编译脚本是同一个目录

source "$PROJECT_ROOT/common/common.sh"

# ========================================================
# 功能实现
# ========================================================
EXECUTE_MODE=manu
function usage()
{
	prt "================================================="
    prt "${PINK}./${SCRIPT_NAME}      : 根据菜单选择功能${CLS}"
    prt "${PINK}./${SCRIPT_NAME} -h   : 显示打印信息用法后显示菜单${CLS}"
    prt "${PINK}./${SCRIPT_NAME} -a   : 自动执行所有步骤${CLS}"
    prt "================================================="
}
# 脚本运行参数处理
notice "There are $# parameters: $@ (\$1~\$$#)"
while getopts "ahp:" arg #选项后面的冒号表示该选项需要参数
    do
        case ${arg} in
            a) EXECUTE_MODE="auto" ;;
            h)
                log_echo_demo
                ;;
            p)
                if [ $OPTARG == "1" ];then
                    message "OPTARG=$OPTARG"
                fi
                ;;
            ?)  #当有不认识的选项的时候arg为?
                error "unkonw argument..."
                exit 1
                ;;
        esac
    done

# 功能函数实现
# ========================================================
# 检查包安装状态函数
function check_install() 
{
    if dpkg-query -W -f='${Status}' "$1" 2>/dev/null | grep -q "ok installed"; then
        return 0
    else
        return 1
    fi
}

# 服务状态检查
function check_service_active() 
{
    systemctl is-active --quiet $1
}

# 卸载nfs-kernel-server
function nfs_uninstall()
{
    execute apt-get purge -y nfs-kernel-server
    execute apt-get purge -y nfs-common
}

# 安装nfs服务端
function nfs_server()
{
    local package=nfs-kernel-server
    # 服务端检测
    if ! check_install ${package}; then
        warning "未检测到${package},即将开始安装"
        execute apt-get update -qq
        # 解决报错：无法创建主目录"/var/lib/nfs"
        execute mkdir -p /var/lib/nfs
        execute chmod 755 /var/lib/nfs
        execute chown nobody:nogroup /var/lib/nfs
        execute apt-get install -y ${package}
    fi
    # 再次检测
    if check_install ${package}; then
        success "nfs服务端${package}已安装,版本如下:"
        # dpkg -l | grep -E "tftp-hpa"
        dpkg -s ${package} | awk -F: '$0 ~ "Version"'
    else
        error "nfs服务端不存在!"
    fi
}

function nfs_client()
{
    local package=nfs-common
    # 客户端检测
    if ! check_installed ${package}; then
        warning "未检测到${package},即将开始安装"
        execute apt-get update -qq
        execute apt-get install -y ${package}
    else
        success "NFS客户端${package}已安装!"
    fi
}

# nfs配置
function nfs_dir_config()
{
    cdi ${SCRIPT_ABSOLUTE_PATH}/etc
    prt "${PINK}current path         :$(pwd)${CLS}"

    # 创建共享目录
    if [ ! -d "${NFS_DIR}" ]; then
        info "创建共享目录: ${NFS_DIR}"
        mkdir -p "${NFS_DIR}"
        chmod 777 "${NFS_DIR}"
        execute chown nobody:nogroup "${NFS_DIR}"
    fi

    # 配置exports文件
    local clients=${CLIENTS:-"*"} # 默认允许所有客户端
    local options=${OPTIONS:-"rw,sync,no_subtree_check,no_root_squash"} # 默认挂载选项
    local nfs_absolute_dir=$(readlink -f "${NFS_DIR}") 
    # 注意这里一定要是绝对路径，否则可能挂载失败
    # /home/sumu/4nfs *(rw,sync,no_subtree_check,no_root_squash)
    local export_entry="${nfs_absolute_dir} ${clients}(${options})"

    if ! grep -qFx "${export_entry}" /etc/exports; then
        info "添加配置到/etc/exports: ${export_entry}"
        execute echo "\"${export_entry}\"" \>\> /etc/exports
        # 应用配置
        execute exportfs -a
        success "NFS共享配置完成"
    else
        warning "该共享配置已存在，跳过重复配置!"
    fi
    # 显示最终共享配置
    info "当前生效的NFS共享"
    execute exportfs -v

    info "重启nfs服务:"
    execute systemctl restart nfs-kernel-server
    success "nfs配置完成"
    cdo
}

# 在一些新版本中nfs老的版本协议不支持，但是对于arm中的开发，例如uboot, kernel它们可能就只支持nfs2.0协议
# ubuntu不支持2.0协议的花，可能就无法实现挂载nfs目录
function nfs_info()
{
    info "nfs支持的所有版本如下:"
    execute cat /proc/fs/nfsd/versions

    # showmount：依赖于nfs-commom
    info "NFS共享目录如下:"
    showmount -e localhost

    info "NFS共享目录实际挂载情况如下:"
    showmount -a # 当前已连接的所有 NFS 客户端及其挂载点‌，输出格式为 客户端IP:挂载目录

    # 查看当前生效配置
    info "NFS共享目录当前生效配置如下:"
    execute exportfs -v
}

function nfs_version_config()
{
    local sys_cfg_file=/etc/default/nfs-kernel-server
    local local_cfg_file=nfs-kernel-server.tmp

    # 将系统配置文件拷贝到当前目录创建临时修改文件，防止权限不足
    cp -pv ${sys_cfg_file} ${local_cfg_file}

    # 处理已存在--nfs-version的情况（添加2.0）
    sed -i -E '/^RPCNFSDOPTS=.*--nfs-version /s/(--nfs-version )([0-9,.]+)/\12,\2/' "$local_cfg_file"
    # 处理没有--nfs-version但存在RPCNFSDOPTS的情况
    sed -i -E '/^RPCNFSDOPTS=/ {/--nfs-version/! s/"(.*)"/"\1 --nfs-version 2,3,4,4.1,4.2"/}' "$local_cfg_file"

    # 处理完全不存在RPCNFSDOPTS行的情况
    if ! grep -q '^RPCNFSDOPTS=' "$local_cfg_file"; then
        echo 'RPCNFSDOPTS="--nfs-version 2,3,4,4.1,4.2"' >> "$local_cfg_file"
    fi

    # 覆盖原来系统的配置文件
    execute cp ${local_cfg_file} ${sys_cfg_file}

    # 重启NFS服务
    info "重启NFS服务..."
    execute systemctl restart nfs-kernel-server

    # 验证结果
    info "当前支持的NFS协议版本:"
    execute cat /proc/fs/nfsd/versions

    # 删除临时文件
    info "删除临时配置文件:${local_cfg_file}"
    rm -rf ${local_cfg_file}
    success "成功更新NFS协议配置!"
}

# nfs测试说明
function nfs_local_check()
{
	info "测试步骤如下:"
	prt "cd ~/4nfs                   # 进入nfs工作目录"
	prt "touch test.txt              # 创建测试文件"
	prt "cd ~                        # 回到家目录"
	prt "sudo mkdir -p /mnt/nfs_temp # 创建挂载目录"
	prt "sudo mount -t nfs localhost:${NFS_DIR} /mnt/nfs_temp # 挂载nfs" 
	prt "ls /mnt/nfs_temp             # 查看是否挂载成功"
	prt "sudo umount /mnt/nfs_temp    # 卸载挂载"
	prt "sudo rm -rf /mnt/nfs_temp    # 卸载挂载"
}

# 自动执行所有步骤
function auto_setup() 
{
    nfs_server
    nfs_client
    nfs_dir_config
    nfs_version_config
    nfs_info
    nfs_local_check
    success "所有步骤执行完成!"
}

# 菜单与主进程
# ========================================================
function show_menu()
{
    message "================================================="
	message "                script by @苏木    ${CLS}"
	message "================================================="
    prt "${PINK}current path         :$(pwd)${CLS}"
    prt "${PINK}PROJECT_ROOT         :${PROJECT_ROOT}${CLS}"
    prt "${PINK}SCRIPT_ABSOLUTE_PATH :${SCRIPT_ABSOLUTE_PATH}${CLS}"
    echo ""
    prt "* [0] 安装nfs服务端和客户端"
    prt "* [1] nfs共享目录配置"
    prt "* [2] nfs2.0协议支持"
    prt "* [3] 查看当前系统nfs信息"
    prt "* [4] 本地主机测试方案"
    prt "* [5] 卸载nfs相关工具"
    echo "================================================="
}

# 主逻辑
function main() 
{
    if [ "$EXECUTE_MODE" = "manu" ]; then
        while true; do
            show_menu
            read -p "请选择操作 (0-5): " choice
            case "${choice}" in
                "0") 
                    nfs_server
                    nfs_client
                    ;;
                "1") nfs_dir_config;;
                "2") nfs_version_config;;
                "3") nfs_info;;
                "4") nfs_local_check;;
                "5") nfs_uninstall;;
                *) error "无效选项!!!" ;;
            esac
            read -p "按回车继续..."
        done
    else
        info "正在自动执行所有配置步骤..."
        auto_setup
    fi
}

# 执行入口
# show_menu # 菜单显示
main "$@" # 主逻辑执行
